﻿using System;
using System.Collections.Generic;
using System.Collections;
using System.Text;
using UserInputWizard.WebReference;
using System.Diagnostics;
using System.IO;
using System.Windows.Forms;

namespace UserInputWizard
{
    class Salesforce
    {
        SforceService sfs = new SforceService();
        private static Salesforce instance;
        private Salesforce(){}
		public static Salesforce getInstance() {
			if (instance == null) {
                instance = new Salesforce();
			}
			return instance;
		}
        /// <summary>
        /// ログインフラグ
        /// </summary>
        private bool m_isLogin = false;
        /// <summary>
        /// ログインフラグ
        /// </summary>
        public bool IsLogin
        {
            get
            {
                return m_isLogin;
            }
            set
            {
                m_isLogin = value;
            }
        }
        List<Profile> profiles = new List<Profile>();
        Hashtable existUsers = new Hashtable();
        List<User> newUsers = new List<User>();

        /// <summary>
        /// ユーザログイン
        /// </summary>
        /// <param name="name">ユーザ名</param>
        /// <param name="pwd">パスワード</param>
        /// <returns>ログイン結果 </returns>
        public bool Login(string name, string pwd, bool isSandbox)
        {
            try
            {
                if (isSandbox)
                {
                    sfs.Url = "https://test.salesforce.com/services/Soap/c/20.0";
                }
                else
                {
                    sfs.Url = "https://login.salesforce.com/services/Soap/c/20.0";
                }
                LoginResult loginResult = sfs.login(name, pwd);
                sfs.Url = loginResult.serverUrl;
                sfs.SessionHeaderValue = new SessionHeader();
                sfs.SessionHeaderValue.sessionId = loginResult.sessionId;
                IsLogin = true;
            }
            catch (Exception ex)
            {
                Log.WriteLine("ログイン失敗しました。");
                Log.WriteLine(ex.Message);
                IsLogin = false;
            }
            return IsLogin;
        }

        /// <summary>
        /// プロファイルを取得
        /// </summary>
        /// <returns></returns>
        public List<Profile> GetProfile()
        {
            

            ///ログイン判断
            if (!IsLogin)
            {
                return profiles;
            }

            ///Queryを生成
            sfs.QueryOptionsValue = new QueryOptions();
            sfs.QueryOptionsValue.batchSize = 200;
            sfs.QueryOptionsValue.batchSizeSpecified = true;
            try
            {
                QueryResult qr = sfs.query("Select Name, Id From Profile");
                bool done = false;
                if (qr.size > 0)
                {
                    profiles.Clear();
                    while (!done)
                    {
                        foreach (Profile profile in qr.records)
                        {
                            profiles.Add(profile);
                        }
                        if (qr.done)
                        {
                            done = true;
                        }
                        else
                        {
                            qr = sfs.queryMore(qr.queryLocator);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Log.WriteLine("プロファイルを取得失敗しました。");
                Log.WriteLine(ex.Message);
            }
            return profiles;
        }
        /// <summary>
        /// ユーザ情報を取得
        /// </summary>
        /// <returns></returns>
        public Hashtable GetUser()
        {
            ///ログイン判断
            if (!IsLogin)
            {
                return existUsers;
            }

            ///Queryを生成
            sfs.QueryOptionsValue = new QueryOptions();
            sfs.QueryOptionsValue.batchSize = 200;
            sfs.QueryOptionsValue.batchSizeSpecified = true;
            try
            {
                QueryResult qr = sfs.query("Select Id, Username, Email From User");
                bool done = false;
                if (qr.size > 0)
                {
                    existUsers.Clear();
                    while (!done)
                    {
                        foreach (User user in qr.records)
                        {
                            existUsers.Add(user.Username,user);
                        }
                        if (qr.done)
                        {
                            done = true;
                        }
                        else
                        {
                            qr = sfs.queryMore(qr.queryLocator);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Log.WriteLine("ユーザ情報を取得失敗しました。");
                Log.WriteLine(ex.Message);
            }
            return existUsers;
        }

        /// <summary>
        /// プロファイル名からプロファイルを取得する
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public Profile GetProfileByName(string name)
        {
            foreach (Profile profile in profiles)
            {
                if (name.Equals(profile.Name))
                {
                    return profile;
                }
            }
            return null;
        }
        /// <summary>
        /// ユーザを作成
        /// </summary>
        /// <param name="FirstName">姓</param>
        /// <param name="LastName">名</param>
        /// <param name="Username">ユーザ名</param>
        /// <param name="Email">電子メール</param>
        /// <param name="profile">プロファイル</param>
        /// <returns>ユーザ</returns>
        public User CreateUser(string FirstName, string LastName, string Username, string Email, Profile profile)
        {
            User user = new User();
            //姓
            user.FirstName = LastName;
            //名
            user.LastName = FirstName;
            //ユーザ名
            user.Username = Username;
            //電子メール
            user.Email = Email;
            //プロファイル
            user.ProfileId = profile.Id;
            //別名
            user.Alias = CreateAlias();
            //有効
            user.IsActive = false;
            //タイムゾーン
            user.TimeZoneSidKey = "Asia/Shanghai";
            //地域
            user.LocaleSidKey = "zh_CN";
            //電子メールの文字コード
            user.EmailEncodingKey = "ISO-8859-1";
            //言語
            user.LanguageLocaleKey = "en_US";
            return user;
        }

        /// <summary>
        /// 別名を乱数で生成する
        /// </summary>
        /// <returns></returns>
        public string CreateAlias()
        {
            int IDSIZE = 6;
            DateTime now = DateTime.Now;
            Random R = new System.Random(Convert.ToInt32(now.Millisecond));
            R.Next(now.Hour * 60 * 60 + now.Second * 60 + now.Minute);
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < IDSIZE; i++)
            {
                int type = R.Next(2);
                char c;
                switch (type)
                {
                    case 0://0~9
                        c = Convert.ToChar(R.Next('0', '9'));
                        break;
                    default://A~Z
                        c = Convert.ToChar(R.Next('A', 'Z'));
                        break;
                }
                sb.Append(c);
            }
            return sb.ToString();
        }

        /// <summary>
        /// デプロイユーザ
        /// </summary>
        /// <param name="newUsers"></param>
        /// <returns></returns>
        public bool DeployUser(List<User> newUsers)
        {
            ///ログイン判断
            if (!IsLogin)
            {
                return false;
            }
            bool isSeccess = true;
            try
            {
                //開始位置
                int startPos = 0;
                //一回デプロイの最大数　200
                int stepLen = 10;
                while (startPos < newUsers.Count)
                {
                    //最大数より小
                    if (newUsers.Count - startPos < stepLen)
                    {
                        stepLen = newUsers.Count - startPos;
                    }
                    //ユーザ情報デプロイ
                    SaveResult [] srs = sfs.create(newUsers.GetRange(startPos, stepLen).ToArray());
                    startPos += stepLen;
                    foreach (SaveResult rs in srs)
                    {
                        if (!rs.success)
                        {
                            Log.WriteLine(rs.id + rs.errors[0].message);
                            isSeccess = false;
                        }
                    }
                }
                return isSeccess;
            }
            catch (Exception ex)
            {
                Log.WriteLine("ユーザ情報をデプロイ失敗しました。");
                Log.WriteLine(ex.Message);
            }
            return false;
        }
        /// <summary>
        /// パスワードを設定する
        /// </summary>
        /// <param name="users"></param>
        /// <param name="newPassword"></param>
        /// <returns></returns>
        public bool SetPassword(User user,string newPassword)
        {
            ///ログイン判断
            if (!IsLogin)
            {
                return false;
            }
            bool isSeccess = true;
            try
            {
                sfs.setPassword(user.Id, newPassword);
            }
            catch (Exception ex)
            {
                isSeccess = false;
                Log.WriteLine("パスワードを設定しました。");
                Log.WriteLine(ex.Message);
            }
            return isSeccess;
        }
    }
}
